<?php
/**
 * PureMVC Port to PHP originally translated by Asbjørn Sloth Tønnesen
 *
 * @author Omar Gonzalez :: omar@almerblank.com
 * @author Hasan Otuome :: hasan@almerblank.com
 *
 * Created on Sep 24, 2008
 * PureMVC - Copyright(c) 2006-2008 Futurescale, Inc., Some rights reserved.
 * Your reuse is governed by the Creative Commons Attribution 3.0 Unported License
 */

/**
 * A Singleton <code>PureMVC_Model_Interface</code> implementation.
 *
 * <P>
 * In PureMVC, the <code>Model</code> class provides
 * access to model objects (Proxies) by named lookup.
 *
 * <P>
 * The <code>Model</code> assumes these responsibilities:</P>
 *
 * <UL>
 * <LI>Maintain a cache of <code>PureMVC_Proxy_Interface</code> instances.</LI>
 * <LI>Provide methods for registering, retrieving, and removing
 * <code>PureMVC_Proxy_Interface</code> instances.</LI>
 * </UL>
 *
 * <P>
 * Your application must register <code>PureMVC_Proxy_Interface</code> instances
 * with the <code>Model</code>. Typically, you use an
 * <code>PureMVC_Command_Interface</code> to create and register <code>PureMVC_Proxy_Interface</code>
 * instances once the <code>Facade</code> has initialized the Core
 * actors.</p>
 *
 * @package org.puremvc.php.core.Model
 * @see org.puremvc.php.patterns.proxy.Proxy Proxy
 * @see org.puremvc.php.interfaces.PureMVC_Proxy_Interface PureMVC_Proxy_Interface
 */
class PureMVC_Model implements PureMVC_Model_Interface
{
	// Mapping of proxyNames to PureMVC_Proxy_Interface instances
	protected $proxyMap;

	// Singleton instance
	protected static $_instance;

	/**
	 * Constructor.
	 *
	 * <P>
	 * This <code>PureMVC_Model_Interface</code> implementation is a Singleton,
	 * so you should not call the constructor
	 * directly, but instead call the static Singleton
	 * Factory method <code>Model.getInstance()</code>
	 *
	 * @throws Error Error if Singleton instance has already been constructed
	 *
	 */
	private function __construct()
	{
		$this->proxyMap = array();
		$this->_initializeModel();
	}
	/**
	 * Initialize the Singleton <code>Model</code> instance.
	 *
	 * <P>
	 * Called automatically by the constructor, this
	 * is your opportunity to initialize the Singleton
	 * instance in your subclass without overriding the
	 * constructor.</P>
	 *
	 * @return void
	 */
	protected function _initializeModel()
	{
	}

	/**
	 * <code>Model</code> Singleton Factory method.
	 *
	 * @return the Singleton instance
	 */
	static public function getInstance()
	{
		if ( self::$_instance == null )
			self::$_instance = new self( );
		return self::$_instance;
	}

	/**
	 * Register an <code>PureMVC_Proxy_Interface</code> with the <code>Model</code>.
	 *
	 * @param proxy an <code>PureMVC_Proxy_Interface</code> to be held by the <code>Model</code>.
	 */
	public function registerProxy( PureMVC_Proxy_Interface $proxy )
	{
		$this->proxyMap[ $proxy->getProxyName() ] = $proxy;
		$proxy->onRegister();
	}

	/**
	 * Retrieve an <code>PureMVC_Proxy_Interface</code> from the <code>Model</code>.
	 *
	 * @param proxyName
	 * @return the <code>PureMVC_Proxy_Interface</code> instance previously registered with the given <code>proxyName</code>.
	 */
	public function retrieveProxy( $proxyName )
	{
		$result = null;
		if ( array_key_exists( $proxyName, $this->proxyMap ) )
		{
			$result = $this->proxyMap[ $proxyName ];
		}
		return $result;
	}

	/**
	 * Remove an <code>PureMVC_Proxy_Interface</code> from the <code>Model</code>.
	 *
	 * @param proxyName name of the <code>PureMVC_Proxy_Interface</code> instance to be removed.
	 */
	public function removeProxy( $proxyName )
	{
		// get a reference to the proxy to be removed
		$proxy = $this->proxyMap[ $proxyName ];

		// remove the instance from the map
		unset( $this->proxyMap[ $proxyName ] );

		// alert the proxy that it has been removed
		$proxy->onRemove();

		return $proxy;
	}

	/**
	 * Check to see if a Proxy is registered with the Model.
	 *
	 * @param proxyName name of the <code>PureMVC_Proxy_Interface</code> instance to check for.
	 */
	public function hasProxy( $proxyName )
	{
		return $this->proxyMap[ $proxyName ] != null;
	}
}

